home *** CD-ROM | disk | FTP | other *** search
/ Tricks of the Mac Game Programming Gurus / TricksOfTheMacGameProgrammingGurus.iso / More Source / Libraries / SAT 2.3b4 / Misc / TransSkel / TransSkel.c < prev    next >
Text File  |  1995-03-30  |  53KB  |  2,116 lines

  1. // This is the PPC ONLY version. It should be conditionally compiled to work
  2. // with all compilers!
  3.  
  4. /*
  5.     TransSkel - Transportable application skeleton
  6.     TransSkel is public domain.
  7.     Version 2.6 of 8/17/90
  8.  
  9.     This version by:
  10.             Bob Schumaker and Dan Hite
  11.             The AMIX Corporation
  12.             2345 Yale Street
  13.             Palo Alto, CA 94306
  14.  
  15.     UUCP:    {sun, uunet}!markets![bob,dan]
  16.     ARPA:    [bob,dan]@amix.com
  17.  
  18.      Originally written by:
  19.             Paul DuBois
  20.             Wisconsin Regional Primate Research Center
  21.             1220 Capital Court
  22.             Madison WI  53706  USA
  23.  
  24.     UUCP:    {allegra,ihnp4,seismo}!uwvax!uwmacc!dubois
  25.     ARPA:    dubois@unix.macc.wisc.edu
  26.             dubois@rhesus.primate.wisc.edu
  27. */
  28.  
  29. /*
  30.     The following symbol controls support for dialogs.
  31.     Changing #define to #undef disables the support.
  32. */
  33.  
  34. #include "TransSkel.h"
  35. //#include "TransSkull.h"
  36. #ifdef applec
  37. #include <Desk.h>
  38. #include <DiskInit.h>
  39. #include <Fonts.h>
  40. #include <Memory.h>
  41. #include <OSEvents.h>
  42. #include <Resources.h>
  43. #include <Script.h>
  44. #include <ToolUtils.h>
  45. #else
  46. #define curSysEnvVers    1
  47. #define zoomDocProc 8
  48. #define    DragGrayRgnProcPtr    ProcPtr
  49. #endif
  50.  
  51. /*
  52.     New(TypeName) returns handle to new object, for any TypeName.
  53.     If there is insufficient memory, the result is nil.
  54. */
  55.  
  56. #define    New(x)    (x **) NewHandle (sizeof (x))
  57.  
  58.  
  59. /*
  60.     Window and Menu handler types, constants, variables.
  61.  
  62.     whList and mhList are the lists of window and menu handlers.
  63.     whClobOnRmve and mhClobOnRmve are true if the handler disposal proc
  64.     is to be called when a handler is removed.  They are temporarily set
  65.     false when handlers are installed for windows or menus that already
  66.     have handlers - the old handler is removed WITHOUT calling the
  67.     disposal proc.
  68.  
  69.     Default lower limits on window sizing of 80 pixels both directions is
  70.     sufficient to allow text windows room to draw a grow box and scroll
  71.     bars without having the thumb and arrows overlap.  These values may
  72.     be changed if such a constraint is undesirable with SkelGrowBounds.
  73.     Default upper limits are for the Macintosh, not the Lisa, but are set
  74.     per machine in SkelInit.
  75. */
  76.  
  77. typedef struct WHandler
  78. {
  79.     WindowPtr    whWind;                        /* window/dialog to be handled    */
  80. //#ifdef applec
  81.     void    (*whClobber)(void);                /* data structure disposal proc */
  82.     void    (*whMouse)(Point, long, short);    /* mouse-click handler proc        */
  83.     void    (*whKey)(char, unsigned char, short);    /* key-click handler proc */
  84.     void    (*whUpdate)(Boolean, short);    /* update handler proc            */
  85.     void    (*whActivate)(Boolean);            /* activate event handler proc    */
  86.     void    (*whClose)(void);                /* close "event" handler proc    */
  87.     void    (*whIdle)(void);                /* main loop proc                */
  88. #ifdef    supportDialogs
  89.     Boolean    (*whEvent)(short *, EventRecord *);/* event hook                */
  90.     Boolean    (*whCheck)(short);                /* hit notify                     */
  91. //#endif
  92. //#else
  93. //    void    (*whClobber)();        /* data structure disposal proc */
  94. //    void    (*whMouse)();        /* mouse-click handler proc        */
  95. //    void    (*whKey)();            /* key-click handler proc        */
  96. //    void    (*whUpdate)();        /* update handler proc            */
  97. //    void    (*whActivate)();    /* activate event handler proc    */
  98. //    void    (*whClose)();        /* close "event" handler proc    */
  99. //    void    (*whIdle)();        /* main loop proc                */
  100. //#ifdef    supportDialogs
  101. //    Boolean    (*whEvent)();        /* event hook                    */
  102. //    Boolean    (*whCheck)();        /* hit notify                    */
  103. //#endif
  104. #endif
  105.     Rect        whGrow;            /* limits on window sizing            */
  106.     RgnHandle    whCursorRgn;    /* cursor region when front window    */
  107.     CursHandle    whCursor;        /* cursor to show while in region    */
  108.     long        userReference;    /* a user specified longword        */
  109.     short        whSizedMods;    /* keys held down while window was resized */
  110. #ifdef supportDialogs
  111.     short        whItemHit;        /* the last item hit in this dialog */
  112.     Boolean        whModal;        /* treat this as a modal dialog?    */
  113. #endif
  114.     Boolean        whCanGrow;        /* this window *can* be grown!!        */
  115.     Boolean        whSized;        /* true = window was resized        */
  116.     Boolean        whFrontOnly;    /* true = idle only when active        */
  117.     Boolean        whHaveCursor;    /* cursor associated with this window */
  118.     struct WHandler    **whNext;    /* next window handler                */
  119. } WHandler;
  120.  
  121. static WHandler    **whList = nil;
  122. static Boolean    whClobOnRmve = true;
  123. static Rect        growRect;
  124. static short mBarHeight;    /* menu bar height.  All window sizing
  125.                               code takes this into account */
  126.  
  127. static RgnHandle cursorRgn;        /* use this to manage the cursor */
  128. static RgnHandle screensRgn;
  129. static Boolean useWaitNextEvent;
  130. static SysEnvRec skelEnvRec;
  131.  
  132. typedef struct MHandler
  133. {
  134.     short            mhID;                        /* menu id                     */
  135. //#ifdef applec
  136.     void            (*mhSelect)(short);            /* item selection handler proc */
  137.     void            (*mhClobber)(MenuHandle);    /* menu disposal handler proc  */
  138. //#else
  139. //    void            (*mhSelect)();            /* item selection handler proc */
  140. //    void            (*mhClobber)();            /* menu disposal handler proc  */
  141. //#endif
  142.     struct MHandler    **mhNext;                    /* next menu handler           */
  143. } MHandler;
  144.  
  145.  
  146. static MHandler    **mhList = nil;            /* list of menu handlers */
  147. static Boolean    mhClobOnRmve = true;
  148.  
  149.  
  150. /*
  151.     Variables for default Apple menu handler.  appleID is set to 1 if
  152.     SkelApple is called and is the id of the Apple menu, appleAboutProc
  153.     is the procedure to execute if there is an About... item and it's
  154.     chosen from the Apple menu.  If doAbout is true, then the menu
  155.     contains the About... item, otherwise it's just desk accessories.
  156. */
  157.  
  158. static MenuHandle    appleMenu;
  159. static short        appleID = 0;
  160. //#ifdef applec
  161. static void            (*appleAboutProc)(void) = nil;
  162. static void            (*appleHelpProc)(void) = nil;
  163. //#else
  164. //static void            (*appleAboutProc)() = nil;
  165. //static void            (*appleHelpProc)() = nil;
  166. //#endif
  167. static Boolean        doAbout = false;
  168. static Boolean        doHelp = false;
  169. /*
  170.     Miscellaneous
  171.  
  172.     screenPort points to the window manager port.
  173.     
  174.     doneFlag determines when SkelMain returns.  It is set by calling
  175.     SkelWhoa(), which the host does to request a halt.
  176.  
  177.     pBkgnd points to a background procedure, to be run during event
  178.     processing.  Set it with SkelBackground.  If nil, there's no
  179.     procedure.
  180.  
  181.     pEvent points to an event-inspecting hook, to be run whenever an
  182.     event occurs.  Set it with SkelEventHook.  If nil, there's no
  183.     procedure.
  184.  
  185.     eventMask controls the event types requested in the GetNextEvent
  186.     call in SkelMain.
  187.  
  188.     diskInitPt is the location at which the disk initialization dialog
  189.     appears, if an uninitialized disk is inserted.
  190. */
  191.  
  192. static GrafPtr    screenPort;
  193. static Boolean    doneFlag = false;
  194.  
  195. //#ifdef applec
  196. static Boolean    (*pEvent)(EventRecord *) = nil;
  197. static void        (*pBkgnd)(void) = nil;
  198. //#else
  199. //static Boolean    (*pEvent)() = nil;
  200. //static void        (*pBkgnd)() = nil;
  201. //#endif
  202. static long     pFGTime = 6L;            /* tenth of a second */
  203. static long        pBGTime = 300L;            /* 5 seconds */
  204. static Boolean    fgApp = true;            /* handle suspend/resume events */
  205.  
  206. static short    eventMask = everyEvent ^ keyUpMask;
  207. static Point    diskInitPt = { /* v = */ 120, /* h = */ 100 };
  208.  
  209. //#ifdef applec
  210. static void (*pScrapConvert)(Boolean) = nil;
  211. static void (*pSuspendResume)(Boolean) = nil;
  212. static void (*pZoomProc)(WindowPtr, short, short, Boolean) = nil;
  213. static void (*pNetworkProc)(EventRecord *) = nil;
  214. static void (*pChildDied)(EventRecord *) = nil;
  215. static void (*pHandleApp4)(EventRecord *) = nil;
  216. //#else
  217. //static void (*pScrapConvert)() = nil;
  218. //static void (*pSuspendResume)() = nil;
  219. //static void (*pZoomProc)() = nil;
  220. //static void (*pNetworkProc)() = nil;
  221. //static void (*pChildDied)() = nil;
  222. //static void (*pHandleApp4)() = nil;
  223. //#endif
  224.  
  225. #ifdef    supportDialogs
  226.  
  227. /*
  228.     Events that are passed to dialogs.  Others are ignored.
  229.     Standard mask passes , mousedown, keydown, autokey, update,
  230.     activate and null events.  Null events are controlled by bit 0.
  231. */
  232.  
  233. static short    dlogEventMask = 0x16b;
  234.  
  235. #endif
  236.  
  237. /* -------------------------------------------------------------------- */
  238. /*                        Internal (private) Routines                        */
  239. /* -------------------------------------------------------------------- */
  240.  
  241. /*
  242.     Get handler associated with user or dialog window.
  243.     Return nil if window doesn't belong to any known handler.
  244.     This routine is absolutely fundamental to TransSkel.
  245. */
  246.  
  247. static WHandler    **GetWDHandler(WindowPtr theWind)
  248. {
  249.     register WHandler    **h;
  250.  
  251.     if (theWind) {
  252.         for (h = whList; h != nil; h = (**h).whNext) {
  253.             if ((**h).whWind == theWind) {
  254.                 return (h);
  255.             }
  256.         }
  257.     }
  258.     return (nil);
  259. }
  260.  
  261.  
  262. /*
  263.     Get handler associated with user window.
  264.     Return nil if window doesn't belong to any known handler.
  265.     The order of the two tests is critical:  theWind might be nil.
  266. */
  267.  
  268. static WHandler    **GetWHandler(WindowPtr theWind)
  269. {
  270.     register WHandler    **h;
  271.  
  272.     if ((h = GetWDHandler (theWind)) != nil
  273.         && ((WindowPeek) theWind)->windowKind != dialogKind) {
  274.         return (h);
  275.     }
  276.     return (nil);
  277. }
  278.  
  279. #ifdef    supportDialogs
  280.  
  281. /*
  282.     Get handler associated with dialog window.
  283.     Return nil if window doesn't belong to any known handler.
  284.     The order of the two tests is critical:  theDialog might be nil.
  285. */
  286.  
  287. static WHandler    **GetDHandler(DialogPtr theDialog)
  288. {
  289.     register WHandler    **h;
  290.  
  291.     if ((h = GetWDHandler (theDialog)) != nil
  292.         && ((WindowPeek) theDialog)->windowKind == dialogKind)
  293.     {
  294.             return (h);
  295.     }
  296.     return (nil);
  297. }
  298.  
  299. #endif
  300.  
  301. static GetPortBounds(WindowPeek winPeek, Rect *bounds)
  302. {
  303.     if ((winPeek->port.portBits.rowBytes & 0xC000) == 0xC000) {
  304.         /* it's a color window!! */
  305.         *bounds = (**((CGrafPtr)(&winPeek->port))->portPixMap).bounds;
  306.     }
  307.     else {
  308.         *bounds = winPeek->port.portBits.bounds;
  309.     }
  310. }
  311.  
  312. static WHandler **SkelNullHandler(WindowPtr theWin)
  313. {
  314.     register WHandler    **h;
  315.     if (h = New (WHandler)) 
  316.     {
  317.         (**h).whWind = theWin;
  318.         (**h).whMouse = nil;
  319.         (**h).whKey = nil;
  320.         (**h).whUpdate = nil;
  321.         (**h).whActivate = nil;
  322.         (**h).whClose = nil;
  323.         (**h).whClobber = nil;
  324.         (**h).whIdle = nil;
  325.         (**h).whFrontOnly = true;
  326.         (**h).whSized = false;
  327.         (**h).whSizedMods = 0;
  328.         (**h).whGrow = growRect;
  329.         (**h).whCanGrow = true;
  330.         (**h).whHaveCursor = false;
  331.         (**h).whCursorRgn = (RgnHandle) 0;
  332.         (**h).whCursor = (CursHandle) 0;
  333.         (**h).userReference = 0L;
  334. #ifdef supportDialogs
  335.         (**h).whEvent = nil;
  336.         (**h).whCheck = nil;
  337.         (**h).whItemHit = 0;
  338.         (**h).whModal = false;
  339. #endif
  340.         /* add this into the window list! */
  341.         (**h).whNext = whList;
  342.         whList = h;
  343.     }
  344.     return (h);
  345. }
  346.  
  347. void SkelDragWindow (WindowPtr theWin, Point pt, short mods, Rect *bounds)
  348. {
  349.     if (!(mods & cmdKey)) {
  350.         SelectWindow (theWin);
  351.         SetPort (theWin);
  352.         if (!StillDown ())
  353.             return;
  354.     }
  355.     DragWindow (theWin, pt, bounds);
  356. }
  357.  
  358. /*
  359.     Remove a menu handler.  This calls the handler's disposal routine
  360.     and then takes the handler out of the handler list and disposes
  361.     of it.
  362.  
  363.     Note that the menu MUST be deleted from the menu bar before calling
  364.     the clobber proc, because the menu bar will end up filled with
  365.     garbage if the menu was allocated with NewMenu (see discussion of
  366.     DisposeMenu in Menu Manager section of Inside Macintosh).
  367.  
  368.     The menu bar is only redrawn if redrawBar is true--this removes
  369.     the flicker from the menu bar when the application terminates.
  370. */
  371.  
  372. static void RemoveMenu(MenuHandle theMenu, Boolean redrawBar)
  373. {
  374.     register short        mID;
  375.     register MHandler    **h, **h2;
  376. //#ifdef applec
  377.     register void        (*p)(MenuHandle);
  378. //#else
  379. //    register void        (*p)();
  380. //#endif
  381.  
  382.     mID = (**theMenu).menuID;
  383.     /* if list empty, ignore */
  384.     if (mhList != nil) {
  385.         /* is it the first element? */
  386.         if ((**mhList).mhID == mID) {
  387.             h2 = mhList;
  388.             mhList = (**mhList).mhNext;
  389.         }
  390.         else {
  391.             for (h = mhList; h != nil; h = h2) {
  392.                 h2 = (**h).mhNext;
  393.                 if (h2 == nil)
  394.                     return;                        /* menu not in list! */
  395.                 if ((**h2).mhID == mID) {
  396.                     /* found it */
  397.                     (**h).mhNext = (**h2).mhNext;
  398.                     break;
  399.                 }
  400.             }
  401.         }
  402.         DeleteMenu (mID);
  403.         if (redrawBar) {
  404.             DrawMenuBar ();
  405.         }
  406.         if (mhClobOnRmve && (p = (**h2).mhClobber) != nil) {
  407.             (*p) (theMenu);                        /* call disposal routine */
  408.         }
  409.         DisposHandle ((Handle) h2);                /* get rid of handler record */
  410.     }
  411. }
  412.  
  413. /*
  414.     General menu-handler.  Just passes selection to the handler's
  415.     select routine.  If the select routine is nil, selecting items from
  416.     the menu is a nop.
  417. */
  418.  
  419. static void DoMenuCommand(long command)
  420. {
  421.     register short        menu;
  422.     register short        item;
  423.     register MHandler    **mh;
  424. //#ifdef applec
  425.     register void        (*p)(short);
  426. //#else
  427. //    register void        (*p)();
  428. //#endif
  429.  
  430.     menu = HiWord (command);
  431.     item = LoWord (command);
  432.     for (mh = mhList; mh != nil; mh = (**mh).mhNext) {
  433.         if ((menu == (**mh).mhID) && ((p = (**mh).mhSelect) != nil)) {
  434.             (*p) (item);
  435.             break;
  436.         }
  437.     }
  438.     HiliteMenu (0);        /* command done, turn off menu hiliting */
  439. }
  440.  
  441.  
  442. /*
  443.     Apple menu handler
  444.     
  445.     DoAppleItem:  If the first item was chosen, and there's an "About..."
  446.     item, call the procedure associated with it (if not nil).  If there
  447.     is no "About..." item or the item was not the first one, then open
  448.     the associated desk accessory.  The port is saved and restored
  449.     because OpenDeskAcc does not always preserve it correctly.
  450.     
  451.     DoAppleClobber disposes of the Apple menu.
  452. */
  453.  
  454. static void DoAppleItem(short item)
  455. {
  456.     GrafPtr        curPort;
  457.     Str255        str;
  458.  
  459.     if (doAbout && item == 1)
  460.     {
  461.         if (appleAboutProc != nil)
  462.             (*appleAboutProc) ();
  463.     }
  464.     else 
  465.         if (doHelp && item == 2) 
  466.         {
  467.             if (appleHelpProc != nil) 
  468.             {
  469.                 (*appleHelpProc) ();
  470.             }
  471.         }
  472.         else
  473.         {
  474.             GetPort (&curPort);
  475.             GetItem (appleMenu, item, str);        /* get DA name */
  476.             (void) OpenDeskAcc (str);            /* open it */
  477.             SetPort (curPort);
  478.         }
  479. }
  480.  
  481. static void DoAppleClobber ()
  482. {
  483.     DisposeMenu (appleMenu);
  484. }
  485.  
  486.  
  487. /* -------------------------------------------------------------------- */
  488. /*                        Window-handler routing routines                    */
  489. /*                                                                        */
  490. /*    Each routine sets the port to the handler's window before executing    */
  491. /*    the handler procedure.                                                */
  492. /* -------------------------------------------------------------------- */
  493.  
  494.  
  495. /*
  496.     Pass local mouse coordinates, click time, and the modifiers flag
  497.     word to the handler.
  498. */
  499.  
  500. static void DoMouse(WHandler **h, EventRecord *theEvent)
  501. {
  502. //#ifdef applec
  503.     register void    (*p)(Point, long, short);
  504. //#else
  505. //    register void    (*p)();
  506. //#endif
  507.     Point            thePt;
  508.  
  509.     if (h != nil) {
  510.         SetPort ((**h).whWind);
  511.         if ((p = (**h).whMouse) != nil) {
  512.             thePt = theEvent->where;    /* make local copy */
  513.             GlobalToLocal (&thePt);
  514.             (*p) (thePt, theEvent->when, theEvent->modifiers);
  515.         }
  516.     }
  517. }
  518.  
  519.  
  520. /*
  521.     Pass the character and the modifiers flag word to the handler.
  522. */
  523.  
  524. static void DoKey(WHandler **h, char ch, unsigned char code, short mods)
  525. {
  526. //#ifdef applec
  527.     register void (*p)(char, unsigned char, short);
  528. //#else
  529. //    register void (*p)();
  530. //#endif
  531.     if (h != nil) {
  532.         SetPort ((**h).whWind);
  533.         if ((p = (**h).whKey) != nil)
  534.             (*p) (ch, code, mods);
  535.     }
  536. }
  537.  
  538.  
  539. /*
  540.     Call the window updating procedure, passing to it an indicator whether
  541.     the window has been resized or not.  Then clear the flag, assuming
  542.     the update proc took whatever action was necessary to respond to
  543.     resizing.
  544.  
  545.     If the handler doesn't have any update proc, the Begin/EndUpdate
  546.     stuff is still done, to clear the update region.  Otherwise the
  547.     Window Manager will keep generating update events for the window,
  548.     stalling updates of other windows.
  549.  
  550.     Make sure to save and restore the port, as it's not always the
  551.     active window that is updated.
  552. */
  553.  
  554. static void DoUpdate (WHandler    **h)
  555. {
  556. //#ifdef applec
  557.     register void        (*p)(Boolean, short);
  558. //#else
  559. //    register void        (*p)();
  560. //#endif
  561.     register GrafPtr    updPort;
  562.     GrafPtr                tmpPort;
  563.  
  564.     if (h != nil) {
  565.         GetPort (&tmpPort);
  566.         SetPort (updPort = (**h).whWind);
  567.         BeginUpdate (updPort);
  568.         if ((p = (**h).whUpdate) != nil) {
  569.             (*p) ((**h).whSized, (**h).whSizedMods);
  570.             (**h).whSized = false;
  571.             (**h).whSizedMods = 0;
  572.         }
  573.         EndUpdate (updPort);
  574.         SetPort (tmpPort);
  575.     }
  576. }
  577.  
  578.  
  579. /*
  580.     Pass activate/deactivate notification to handler.
  581. */
  582.  
  583. static void DoActivate(WindowPtr theWin, Boolean active)
  584. {
  585. //#ifdef applec
  586.     register void (*p)(Boolean);
  587. //#else
  588. //    register void (*p)();
  589. //#endif
  590.     WHandler    **h;
  591.  
  592.     if ((h = GetWDHandler (theWin)) != nil) {
  593.         SetPort ((**h).whWind);
  594.         if ((p = (**h).whActivate) != nil) {
  595.             (*p) (active);
  596.         }
  597.         /* reset the cursor region */
  598.         if (active) {
  599.             SetEmptyRgn (cursorRgn);
  600.         }
  601.     }
  602. }
  603.  
  604.  
  605. /*
  606.     Execute a window handler's close proc.  This may be used by handlers
  607.     for temp windows that want to remove themselves when the window
  608.     is closed:  they can call SkelRmveWind to dispose of the window
  609.     and remove the handler from the window handler list.  Thus, windows
  610.     may be dynamically created and destroyed without filling up the
  611.     handler list with a bunch of invalid handlers.
  612.     
  613.     If the handler doesn't have a close proc, just hide the window.
  614.     The host should provide some way of reopening the window (perhaps
  615.     a menu selection).  Otherwise the window will be lost from user
  616.     control if it is hidden, since it won't receive user events.
  617.  
  618.     The port is set to the window manager port after calling the
  619.     handler proc, to avoid a dangling port.
  620.  
  621.     This is called both for regular and dialog windows.
  622. */
  623.  
  624. static void DoClose (WHandler **h)
  625. {
  626. //#ifdef applec
  627.     register void        (*p)(void);
  628. //#else
  629. //    register void        (*p)();
  630. //#endif
  631.     GrafPtr savePort;
  632.  
  633.     if (h != nil) {
  634.         if ((p = (**h).whClose) != nil) {
  635.             GetPort (&savePort);
  636.             SetPort ((**h).whWind);
  637.             (*p) ();
  638.             SetPort (savePort);
  639.         }
  640.         else {
  641.             HideWindow ((**h).whWind);
  642.         }
  643.     }
  644. }
  645.  
  646.  
  647. /*
  648.     Execute a window handler's clobber proc.
  649.  
  650.     The port is set to the window manager port after calling the
  651.     handler proc, to avoid a dangling port.
  652.  
  653.     This is called both for regular and dialog windows.
  654. */
  655.  
  656. static void DoClobber (WHandler **h)
  657. {
  658. //#ifdef applec
  659.     register void (*p)(void);
  660. //#else
  661. //    register void (*p)();
  662. //#endif
  663.     GrafPtr    tmpPort;
  664.  
  665.     GetPort (&tmpPort);
  666.     SetPort ((**h).whWind);
  667.     if ((p = (**h).whClobber) != nil)
  668.         (*p) ();
  669.     SetPort (tmpPort);
  670. }
  671.  
  672.  
  673. /*
  674.     Execute handler's idle proc.
  675.  
  676.     Make sure to save and restore the port, since idle procs may be
  677.     called for any window, not just the active one.
  678. */
  679.  
  680. static void DoIdle (WHandler **h)
  681. {
  682. //#ifdef applec
  683.     register void (*p)(void);
  684. //#else
  685. //    register void (*p)();
  686. //#endif
  687.     GrafPtr            tmpPort;
  688.  
  689.     if (h != nil) 
  690.     {
  691.         if (!useWaitNextEvent) 
  692.         {
  693.             SystemTask ();
  694.         }
  695.         GetPort (&tmpPort);
  696.         SetPort ((**h).whWind);
  697.         if ((p = (**h).whIdle) != nil)
  698.             (*p) ();
  699.         SetPort (tmpPort);
  700.     }
  701. }
  702.  
  703.  
  704. #ifdef    supportDialogs
  705.  
  706. /* -------------------------------------------------------------------- */
  707. /*                            Dialog-handling routines                    */
  708. /* -------------------------------------------------------------------- */
  709.  
  710.  
  711. /*
  712.     Handle event if it's for a dialog.  The event must be one of
  713.     those that is passed to dialogs according to dlogEventMask.
  714.     This mask can be set so that disk-inserts, for instance, don't
  715.     get eaten up.
  716. */
  717.  
  718. static Boolean DoDialog (EventRecord *evt)
  719. {
  720.     register WHandler    **dh;
  721.     DialogPtr            theDialog;
  722.     register short        what;
  723.     short                item;
  724.     Boolean                handledIt = false;
  725. //#ifdef applec
  726.     Boolean                (*pKeys)(short *, EventRecord *);
  727. //#else
  728. //    Boolean                (*pKeys)();
  729. //#endif
  730.  
  731.     theDialog = (DialogPtr) FrontWindow ();
  732.     if ((dh = GetDHandler (theDialog)) != nil) {
  733. //#ifdef applec
  734.         pKeys = (Boolean (*)(short *, EventRecord *)) (**dh).whKey;
  735. //#else
  736. //        pKeys = (Boolean (*)()) (**dh).whKey;
  737. //#endif
  738.     }
  739.     else {
  740.         pKeys = nil;
  741.     }
  742.     what = evt->what;
  743. /* handle command keys before they get to IsDialogEvent */
  744.     if ((what == keyDown || what == autoKey) && (evt->modifiers & cmdKey)) {
  745.         if (!(pKeys && (handledIt = (*pKeys) (&item, evt)))) {
  746.             if (!(dh && (**dh).whModal)) {
  747.                 DoMenuCommand (MenuKey (evt->message & charCodeMask));
  748.             }
  749.             return (true);
  750.         }
  751.     }
  752.     else if (what == app4Evt || what == updateEvt) {
  753.         /* do multifinder events, updates are handled in the main loop */
  754.         if (dh && (**dh).whEvent) {
  755.             handledIt = (*(**dh).whEvent)(&item, evt);
  756.         }
  757.         return (handledIt);               /* main section handles these */
  758.     }
  759.     else if (((1 << what) & dlogEventMask) && IsDialogEvent (evt)) {
  760.         item = 0;
  761.         switch (what) {
  762.             case keyDown:
  763.             case autoKey:
  764.                 if (!(pKeys && (handledIt = (*pKeys) (&item, evt)))) {
  765.                     handledIt = DialogSelect (evt, &theDialog, &item);
  766.                 }
  767.                 break;
  768.             case activateEvt:                        /* if activate */
  769.                 theDialog = (DialogPtr) evt->message;
  770.                 dh = GetDHandler ((WindowPtr) theDialog);
  771.                 if ((evt->modifiers & activeFlag)    /* and coming active */
  772.                     && ((WindowPeek) theDialog)->windowKind == dialogKind) {
  773.                     SetPort ((GrafPtr) theDialog);
  774.                 }
  775.             /* fall through */
  776.             default:
  777.                 if (!(dh && (**dh).whEvent &&
  778.                         (handledIt = (*(**dh).whEvent)(&item, evt))    )) {
  779.                     handledIt = DialogSelect (evt, &theDialog, &item);
  780.                 }
  781.                 break;
  782.         }
  783.         if ((dh = GetDHandler ((WindowPtr) theDialog)) != nil) {
  784.             (**dh).whItemHit = item;
  785.             /* if this is a modal dialog, whCheck will be called elsewhere */
  786.             if ((**dh).whCheck && !(**dh).whModal) {
  787.                 (*(**dh).whCheck) (item);
  788.             }
  789.         }
  790.     }
  791.     return (handledIt);
  792. }
  793.  
  794. #endif
  795.  
  796. /* -------------------------------------------------------------------- */
  797. /*                            Event-handling routines                        */
  798. /* -------------------------------------------------------------------- */
  799.  
  800.  
  801. static void SkelCheckCursor(WHandler **wh, Point mouse, RgnHandle region)
  802. {
  803.     Point pt;
  804.     RgnHandle arrowRgn, localRgn;
  805.  
  806.     if (wh && (**wh).whHaveCursor) 
  807.     {
  808.         arrowRgn = NewRgn ();
  809.         localRgn = NewRgn ();
  810.         CopyRgn ((**wh).whCursorRgn, localRgn);
  811.         CopyRgn (screensRgn, arrowRgn);
  812.         SetPt (&pt, 0, 0);
  813.         SetPort ((**wh).whWind);
  814.         LocalToGlobal (&pt);
  815.         OffsetRgn (localRgn, pt.h, pt.v);
  816.         DiffRgn (arrowRgn, localRgn, arrowRgn);
  817.  
  818.         if (PtInRgn (mouse, localRgn)) 
  819.         {
  820.             SetCursor (*(**wh).whCursor);
  821.             CopyRgn (localRgn, region);
  822.         }
  823.         else {
  824.             InitCursor ();
  825.             CopyRgn (arrowRgn, region);
  826.         }
  827.         DisposeRgn (localRgn);
  828.         DisposeRgn (arrowRgn);
  829.     }
  830.     else {
  831.         InitCursor ();
  832.         CopyRgn (screensRgn, region);
  833.     }
  834. }
  835.  
  836. /*
  837.     Have either zoomed a window or sized it manually.  Invalidate
  838.     it to force an update and set the 'resized' flag in the window
  839.     handler true.  The port is assumed to be set to the port that changed
  840.     size.
  841. */
  842.  
  843. static void TriggerUpdate(WHandler **h, GrafPtr grownPort, short mods)
  844. {
  845.     GrafPtr savePort;
  846.  
  847.     GetPort (&savePort);
  848.     SetPort (grownPort);
  849.     InvalRect (&grownPort->portRect);
  850.     if (h != nil) {
  851.         (**h).whSized = true;
  852.         (**h).whSizedMods = mods;
  853.         if ((**h).whHaveCursor && grownPort == FrontWindow ()) 
  854.         {
  855.             SetEmptyRgn (cursorRgn);
  856.         }
  857.     }
  858.     SetPort (savePort);
  859. }
  860.  
  861. /*
  862.     Size a window.  If the window has a handler, use the grow limits
  863.     in the handler record, otherwise use the defaults.
  864.  
  865.     The portRect is invalidated to force an update event.  (The port
  866.     must be set first, as it could be pointing anywhere.)  The handler's
  867.     update procedure should check the parameter passed to it to check
  868.     whether the window has changed size, if it needs to adjust itself to
  869.     the new size.  THIS IS A CONVENTION.  Update procs must notice grow
  870.     "events", there is no procedure specifically for such events.
  871.     
  872.     The clipping rectangle is not reset.  If the host application
  873.     keeps the clipping set equal to the portRect or something similar,
  874.     then it will have to arrange to treat window growing with more
  875.     care.
  876.  
  877.     Since the grow region of only the active window may be clicked,
  878.     it should not be necessary to set the port.
  879. */
  880.  
  881. static void DoGrow(WHandler **h, GrafPtr thePort, Point startPt, short mods)
  882. {
  883.     Rect                r;
  884.     register long        growRes;
  885.  
  886.     r = (**h).whGrow;
  887.     /* grow result non-zero if size change    */
  888.     if (growRes = GrowWindow (thePort, startPt, &r)) {
  889.         SizeWindow (thePort, LoWord (growRes), HiWord (growRes), false);
  890.         TriggerUpdate (h, thePort, mods);
  891.     }
  892. }
  893.  
  894.  
  895. /*
  896.     Zoom the current window.  Very similar to DoGrow
  897.  
  898.     Since the zoombox of only the active window may be clicked,
  899.     it should not be necessary to set the port.
  900. */
  901.  
  902. static void DoZoom(WHandler **h, GrafPtr zoomPort, short partCode, short mods)
  903. {
  904.     if (pZoomProc) 
  905.     {
  906.         /* for a custom zoom proc, allow the user to modify the behaviour */
  907.         (*pZoomProc) (zoomPort, partCode, mods, false);
  908.     }
  909.     else 
  910.         {
  911.             ZoomWindow (zoomPort, partCode, false);
  912.     }
  913.     TriggerUpdate (h, zoomPort, mods);
  914. }
  915.  
  916. /*
  917.     General event handler
  918. */
  919.  
  920. static void DoEvent (EventRecord *theEvt)
  921. {
  922.     register EventRecord    *theEvent;
  923.     Point                    evtPt;
  924.     GrafPtr                    evtPort;
  925.     register short            evtPart;
  926.     register char            evtChar;
  927.     register unsigned char    evtCode;
  928.     register short            evtMods = 0;
  929.     register WHandler        **h, **t;
  930.     Rect                    r;
  931.     WindowPtr                frontWindow = FrontWindow ();
  932.  
  933.     theEvent = theEvt;
  934.  
  935. #ifdef    supportDialogs
  936.     if(DoDialog (theEvent))
  937.         return;
  938. #endif
  939.  
  940.     evtPt = theEvent->where;
  941.     evtMods = theEvent->modifiers;
  942.  
  943.     switch (theEvent->what) 
  944.     {
  945.         case app4Evt:        /* multifinder event */
  946.             {
  947.                 short flag = ((theEvent->message >> 24) & 0xff);
  948.                 if (flag == 0x01) {
  949.                     fgApp = ((theEvent->message & 0x01) != 0);
  950.                     DoActivate (frontWindow, fgApp);
  951.                     /* does the app want to know about suspend/resume? */
  952.                     if (pSuspendResume) {
  953.                         (*pSuspendResume)(fgApp);
  954.                     }
  955.                     /* should we convert the scrap?  Always convert if suspend
  956.                        but only convert on resume if "changed scrap" flag bit is set */
  957.                     if ((!fgApp || (theEvent->message & 0x02)) && pScrapConvert) {
  958.                         (*pScrapConvert)(fgApp);
  959.                     }
  960.                 }
  961.                 else if (flag == 0xfa && fgApp) {
  962.                     SkelCheckCursor (GetWDHandler (frontWindow), evtPt, cursorRgn);
  963.                 }
  964.                 else if (flag == 0xfd) {
  965.                     if (pChildDied) {
  966.                         (*pChildDied) (theEvent);
  967.                     }
  968.                 }
  969.                 else if (pHandleApp4) {
  970.                     (*pHandleApp4) (theEvent);
  971.                 }
  972.             }
  973.             /* fall through to do "idle" processing */
  974.         case nullEvent:
  975.             if (pBkgnd != nil) {
  976.                 (*pBkgnd) ();
  977.             }
  978.             if (!useWaitNextEvent && !PtInRgn (evtPt, cursorRgn)) {
  979.                 SkelCheckCursor (GetWDHandler (frontWindow), theEvent->where, cursorRgn);
  980.             }
  981.             break;
  982. /*
  983.     Mouse click.  Get the window that the click occurred in, and the
  984.     part of the window.
  985. */
  986.         case mouseDown:
  987.         {
  988.             evtPart = FindWindow (evtPt, &evtPort);
  989.             h = GetWHandler (evtPort);
  990. #ifdef supportDialogs
  991.             /* don't allow mouse clicks outside a modal dialog */
  992.             if (evtPort != frontWindow &&
  993.                     (t = GetWDHandler(FrontWindow())) != nil &&
  994.                     (**t).whModal) {
  995.                 break;
  996.             }
  997. #endif
  998.             switch (evtPart)
  999.             {
  1000. /*
  1001.     Click in a desk accessory window.  Pass back to the system.
  1002. */
  1003.                 case inSysWindow:
  1004.                 {
  1005.                     SystemClick (theEvent, evtPort);
  1006.                     break;
  1007.                 }
  1008. /*
  1009.     Click in menu bar.  Track the mouse and execute selected command,
  1010.     if any.
  1011. */
  1012.                 case inMenuBar:
  1013.                 {
  1014.                     DoMenuCommand (MenuSelect (evtPt));
  1015.                     break;
  1016.                 }
  1017. /*
  1018.     Click in grow box.  Resize window.
  1019. */
  1020.                 case inGrow:
  1021.                 {
  1022.                     if (h) {
  1023.                         if ((**h).whCanGrow) {
  1024.                             DoGrow (h, evtPort, evtPt, evtMods);
  1025.                         }
  1026.                         else {
  1027.                             DoMouse (h, theEvent);
  1028.                         }
  1029.                     }
  1030.                     break;
  1031.                 }
  1032. /*
  1033.     Click in title bar.  Drag the window around.  Leave at least
  1034.     4 pixels visible in both directions.
  1035.     Bug fix:  The window is selected first to make sure it's at least
  1036.     activated (unless the command key is down-see Inside Macintosh).
  1037.     DragWindow seems to call StillDown first, so that clicks in drag
  1038.     regions while machine is busy don't otherwise bring window to front if
  1039.     the mouse is already up by the time DragWindow is called.
  1040. */
  1041.                 case inDrag:
  1042.                 {
  1043.                     r = screenPort->portRect;
  1044.                     r.top += mBarHeight;            /* skip down past menu bar */
  1045.                     InsetRect (&r, 4, 4);
  1046.                     SkelDragWindow (evtPort, evtPt, evtMods, &r);
  1047.                     break;
  1048.                 }
  1049. /*
  1050.     Click in close box.  Call the close proc if the window has one.
  1051. */
  1052.                 case inGoAway:
  1053.                 {
  1054.                     if (TrackGoAway (evtPort, evtPt))
  1055.                         DoClose (h);
  1056.                     break;
  1057.                 }
  1058. /*
  1059.     Click in content region.  If the window wasn't frontmost (active),
  1060.     just select it, otherwise pass the click to the window's mouse
  1061.     click handler.
  1062. */
  1063.                 case inContent:
  1064.                 {
  1065.                     if (evtPort != frontWindow) {
  1066.                         SelectWindow (evtPort);
  1067.                         SetPort (evtPort);
  1068.                     }
  1069.                     else
  1070.                         DoMouse (h, theEvent);
  1071.                     break;
  1072.                 }
  1073.  
  1074. /*
  1075.     Click in zoom box.  Track the click and then zoom the window if
  1076.     necessary
  1077. */
  1078.                 case inZoomIn:
  1079.                 case inZoomOut:
  1080.                 {
  1081.                     if(TrackBox(evtPort, evtPt, evtPart))
  1082.                         DoZoom (h, evtPort, evtPart, evtMods);
  1083.                     break;
  1084.                 }
  1085.  
  1086.             }
  1087.             break;    /* mouseDown */
  1088.         }
  1089. /*
  1090.     Key event.  If the command key was down, process as menu item
  1091.     selection, otherwise pass the character and the modifiers flags
  1092.     to the active window's key handler.
  1093.  
  1094.     If dialogs are supported, there's no check for command-key
  1095.     equivalents, since that would have been checked in DoDialog.
  1096. */
  1097.         case keyDown:
  1098.         case autoKey:
  1099.         {
  1100.             evtCode = (theEvent->message & keyCodeMask) >> 8;
  1101.             evtChar = theEvent->message & charCodeMask;
  1102. #ifndef supportDialogs
  1103.             if (evtMods & cmdKey) {
  1104.                 /* try menu equivalent */
  1105.                 DoMenuCommand (MenuKey (evtChar));
  1106.                 break;
  1107.             }
  1108. #endif
  1109.             /* frontWindow is at least frontDocWindow--
  1110.                 tools can't get keys! (Yet!!) */
  1111.             DoKey (GetWHandler (frontWindow), evtChar, evtCode, evtMods);
  1112.             break;
  1113.         }
  1114.  
  1115.         case keyUp:
  1116.         {
  1117.             evtCode = 0x80 | ( (theEvent->message & keyCodeMask) >> 8 );
  1118.             evtChar = theEvent->message & charCodeMask;
  1119.  
  1120.             DoKey (GetWHandler (frontWindow), evtChar, evtCode, evtMods);
  1121.             break;
  1122.         }
  1123.         
  1124. /*
  1125.     Update a window.
  1126. */
  1127.         case updateEvt:
  1128.         {
  1129.             DoUpdate (GetWDHandler ((WindowPtr) theEvent->message));
  1130.             break;
  1131.         }
  1132. /*
  1133.     Activate or deactivate a window.
  1134. */
  1135.         case activateEvt:
  1136.         {
  1137.             DoActivate ((WindowPtr) theEvent->message,
  1138.                         ((theEvent->modifiers & activeFlag) != 0));
  1139.             break;
  1140.         }
  1141. /*
  1142.     handle inserts of uninitialized disks
  1143. */
  1144.         case diskEvt:
  1145.         {
  1146.             if (HiWord (theEvent->message) != noErr) {
  1147.                 DILoad ();
  1148.                 (void) DIBadMount (diskInitPt, theEvent->message);
  1149.                 DIUnload ();
  1150.             }
  1151.             break;
  1152.         }
  1153. /*
  1154.     handle network events
  1155. */
  1156.         case networkEvt:
  1157.         {
  1158.             if (pNetworkProc) {
  1159.                 (*pNetworkProc) (theEvent);
  1160.             }
  1161.             break;
  1162.         }
  1163.     }
  1164. }
  1165.  
  1166.  
  1167. /* -------------------------------------------------------------------- */
  1168. /*                        Interface (public) Routines                        */
  1169. /* -------------------------------------------------------------------- */
  1170.  
  1171.  
  1172. /*
  1173.     Initialize the various Macintosh Managers.
  1174.     Set default upper limits on window sizing.
  1175.     FlushEvents does NOT toss disk insert events, so that disks
  1176.     inserted while the application is starting up don't result
  1177.     in dead drives.
  1178.     Determine whether to use WaitNextEvent or not.
  1179.     Set up big rectangle for cursor management.
  1180. */
  1181. #define _WaitNextEvent 0xA860
  1182.  
  1183. void SkelInit(void (*resume)(), int extra)
  1184. {
  1185.     Rect r;
  1186.     
  1187.     MaxApplZone ();
  1188.     FlushEvents (everyEvent - diskMask, 0 );
  1189. #ifdef THINK_C
  1190.     InitGraf (&thePort);
  1191. #else
  1192.     InitGraf (&qd.thePort);
  1193. #endif
  1194.     InitFonts ();
  1195.     InitWindows ();
  1196.     InitMenus ();
  1197.     TEInit ();
  1198. #ifdef applec
  1199.     InitDialogs ((ResumeProcPtr) resume);        /* no restart proc */
  1200. #else
  1201. #ifdef THINK_C
  1202.     InitDialogs ((ProcPtr) resume);        /* no restart proc */
  1203. #else
  1204.     InitDialogs(0);
  1205. #endif
  1206. #endif
  1207.  
  1208.     InitCursor ();
  1209.  
  1210.     while (extra-- > 0)
  1211.         MoreMasters ();
  1212.  
  1213. /*
  1214.     Set upper limits of window sizing to machine screen size.  Allow
  1215.     for the menu bar (use the glue from the Script Manager).
  1216. */
  1217.     GetWMgrPort (&screenPort);
  1218.     growRect.top = 80;
  1219.     growRect.left = 80;
  1220.     growRect.right = screenPort->portRect.right;
  1221.     growRect.bottom = screenPort->portRect.bottom - (mBarHeight = GetMBarHeight ());
  1222.  
  1223.     /* this is (at this time anyway) pointless */
  1224.     SkelEventMask (eventMask);
  1225.  
  1226.     /* throw away any error return */
  1227.     (void) SysEnvirons (curSysEnvVers, &skelEnvRec);
  1228.     useWaitNextEvent = true; // PPC always has WNE! SkelCheckTrap (_WaitNextEvent, ToolTrap);
  1229.  
  1230.     /* build a region that covers all of the displays available */
  1231.     screensRgn = NewRgn ();
  1232.     SetRect (&r, -32768, -32768, 32767, 32767);
  1233.     /* account for bug in 128K ROMs */
  1234.     if (skelEnvRec.machineType < envMacII)
  1235.         InsetRect (&r, 1, 1);
  1236.     RectRgn (screensRgn, &r);
  1237.     /* a place to watch the cursor in */
  1238.     cursorRgn = NewRgn ();
  1239. }
  1240.  
  1241. /*
  1242.     Main loop.
  1243.  
  1244.     Take care of DA's with SystemTask (not needed with WaitNextEvent).
  1245.     Run background task if there is one. (now at nullEvents in DoEvent)
  1246.     If there is an event, check for an event hook.  If there isn't
  1247.     one defined, or if there is but it returns false, call the
  1248.     general event handler.  (Hook returns true if TransSkel should
  1249.     ignore the event.)
  1250.     If no event, call the "no-event" handler for the front window and for
  1251.     any other windows with idle procedures that are always supposed
  1252.     to run.  This is done in such a way that it is safe for idle procs
  1253.     to remove the handler for their own window if they want (unlikely,
  1254.     but...)  This loop doesn't check whether the window is really
  1255.     a dialog window or not, but it doesn't have to, because such
  1256.     things always have a nil idle proc.
  1257.     
  1258.     doneFlag is reset upon exit.  This allows it to be called
  1259.     repeatedly, or recursively.
  1260.  
  1261.     If dialogs are supported, null events are looked at (in SkelMain)
  1262.     and passed to the event handler.  This is necessary to make sure
  1263.     DialogSelect gets called repeatedly, or the caret won't blink if
  1264.     a dialog has any editText items.
  1265.  
  1266.     In order to be more multi-finder compatible, null-events are passed
  1267.     through to doEvent--where the appropriate idle processing is done.
  1268. */
  1269.  
  1270. Boolean SkelWaitNextEvent(short evtMask, EventRecord *evt, 
  1271.                     long timeOut, RgnHandle checkRgn)
  1272. {
  1273.     if (useWaitNextEvent) {
  1274.         return (WaitNextEvent (evtMask, evt, timeOut, checkRgn));
  1275.     }
  1276.     else {
  1277.         SystemTask ();
  1278.         return (GetNextEvent (evtMask, evt));
  1279.     }
  1280. }
  1281.  
  1282. /*
  1283.     if checkRgn is nil then mouse-moved events *won't* be generated
  1284. */
  1285. void SkelOnePass (RgnHandle checkRgn)
  1286. {
  1287.     EventRecord            theEvent;
  1288.     register WHandler    **wh, **wh2;
  1289.     Boolean                haveEvent;
  1290.     WindowPtr            frontWindow;
  1291.     long                timeOut = pBGTime;
  1292.  
  1293. /*
  1294.     Now watch carefully.  GetNextEvent calls SystemEvent to handle some
  1295.     DA events, and returns false if the event was handled.  However, in
  1296.     such cases the event record will still have the event that occurred,
  1297.     *not* a null event, as you might reasonably expect.  So it's not
  1298.     enough to look at haveEvent.
  1299.  
  1300.     Previous versions figured (wrongly) that haveEvent==false meant a null
  1301.     event had occurred, and passed it through to DoEvent and DoDialog, so
  1302.     that caret-blinking in dialog TextEdit items would occur.  But cmd-key
  1303.     equivalents while DA windows were in front, in particular, allowed
  1304.     already-processed DA events to get into DoEvent (because haveEvent
  1305.     was false), and they got handled twice because when the event record
  1306.     was examined, lo and behold, it had a cmd-key event!  So now this
  1307.     logic is used:
  1308.  
  1309.     If have a real event, and there's no event hook or there is but it
  1310.     doesn't handle the event, OR if the "non-event" is a true nullEvent,
  1311.     then process it. (modified to allow nullEvents to go to event hook)
  1312. */
  1313.         
  1314.     if (fgApp) {
  1315.         timeOut = pFGTime;
  1316.     }
  1317.     haveEvent = SkelWaitNextEvent (eventMask, &theEvent, timeOut, checkRgn);
  1318.  
  1319.     /* ignore haveEvent here so that event hook will get null events
  1320.        a check for a nullEvent is pretty silly in this case */
  1321.     if ((pEvent == nil || (*pEvent)(&theEvent) == false))
  1322.         DoEvent(&theEvent);
  1323.  
  1324. /*
  1325.     Run applicable idle procs.  Make sure to save and restore the port,
  1326.     since idle procs for the non-active window may be run.
  1327. */
  1328.     if (!haveEvent || theEvent.what == nullEvent) {
  1329.         frontWindow = FrontWindow ();
  1330.         for (wh = whList; wh != nil; wh = wh2) {
  1331.             wh2 = (**wh).whNext;
  1332.             if ((**wh).whWind == frontWindow || !(**wh).whFrontOnly) {
  1333.                 DoIdle (wh);
  1334.             }
  1335.         }
  1336.     }
  1337. }
  1338.  
  1339. void SkelMain ()
  1340. {
  1341. #ifdef    CHECK_STACK
  1342.     long stackFree;
  1343. #endif
  1344.     /* create a region to do cursor handling in */
  1345.     while (!doneFlag) {    
  1346.         SkelOnePass (cursorRgn);
  1347. #ifdef    CHECK_STACK
  1348.         stackFree = StackSpace ();
  1349. #endif
  1350.     }
  1351.     doneFlag = false;
  1352.     /* ditch the cursor control region */
  1353. }
  1354.  
  1355.  
  1356. /*
  1357.     Tell SkelMain to stop
  1358. */
  1359.  
  1360. void SkelWhoa ()
  1361. {
  1362.     doneFlag = true;
  1363. }
  1364.  
  1365.  
  1366. /*
  1367.     Clobber all the menu, window and dialog handlers
  1368. */
  1369.  
  1370. void SkelClobber ()
  1371. {
  1372.     while (whList != nil)
  1373.         SkelRmveWind ((**whList).whWind);
  1374.  
  1375.     /* 'false' removes the annoying flicker as menus are deleted */
  1376.     while (mhList != nil)
  1377.         RemoveMenu (GetMHandle((**mhList).mhID), false);
  1378.     /* draw the menu bar (now empty) in case there's some system level cleanup */
  1379.     DrawMenuBar ();
  1380.     DisposeRgn (cursorRgn);
  1381.     /* make the event mask innocuous for uniFinder */
  1382.     SetEventMask (everyEvent ^ keyUpMask);
  1383. }
  1384.  
  1385.  
  1386. /* -------------------------------------------------------------------- */
  1387. /*                        Menu-handler interface routines                    */
  1388. /* -------------------------------------------------------------------- */
  1389.  
  1390.  
  1391. /*
  1392.     Install handler for a menu.  Remove any previous handler for it.
  1393.     Pass the following parameters:
  1394.  
  1395.     theMenu    Handle to the menu to be handled.  Must be created by host.
  1396.     pSelect    Proc that handles selection of items from menu.  If this is
  1397.             nil, the menu is installed, but nothing happens when items
  1398.             are selected from it.
  1399.     pClobber Proc for disposal of handler's data structures.  Usually
  1400.             nil for menus that remain in menu bar until program
  1401.             termination.
  1402.     isPull    Should this be installed in the menubar?
  1403.     drawBar    draw the menu bar?
  1404. */
  1405.  
  1406. void SkelMenu(MenuHandle theMenu, 
  1407.     void (*pSelect)(short), 
  1408.     void (*pClobber)(MenuHandle), 
  1409.     Boolean isPull, 
  1410.     Boolean drawBar)
  1411. {
  1412.     register MHandler    **mh;
  1413.  
  1414.     mhClobOnRmve = false;
  1415.     SkelRmveMenu (theMenu);
  1416.     mhClobOnRmve = true;
  1417.  
  1418.     mh = New (MHandler);
  1419.     (**mh).mhNext = mhList;
  1420.     mhList = mh;
  1421.     (**mh).mhID = (**theMenu).menuID;            /* get menu id number */
  1422.     (**mh).mhSelect = pSelect;                    /* install selection handler */
  1423.     (**mh).mhClobber = pClobber;                /* install disposal handler */
  1424.     InsertMenu (theMenu, (isPull) ? -1 : 0);    /* insert menu in menulist */
  1425.     if (drawBar)
  1426.         DrawMenuBar ();
  1427. }
  1428.  
  1429. /*
  1430.     Remove a menu from the menu list for the user
  1431. */
  1432.  
  1433. void SkelRmveMenu (MenuHandle theMenu)
  1434. {
  1435.     /* 'true' forces the menubar to be redrawn */
  1436.     RemoveMenu (theMenu, true);
  1437. }
  1438.  
  1439. /*
  1440.     Install a handler for the Apple menu.
  1441.     
  1442.     SkelApple is called if TransSkel is supposed to handle the apple
  1443.     menu itself.  aboutTitle is the title of the first item.  If nil,
  1444.     then only desk accessories are put into the menu.  If not nil, then
  1445.     the title is entered as the first item, followed by a gray line,
  1446.     then the desk accessories.
  1447.  
  1448.     SkelApple does not cause the menubar to be drawn, so if the Apple
  1449.     menu is the only menu, DrawMenuBar must be called afterward.
  1450.  
  1451.     No value is returned, unlike SkelMenu.  It is assumed that SkelApple
  1452.     will be called so early in the application that the call the SkelMenu
  1453.     is virtually certain to succeed.  If it doesn't, there's probably
  1454.     little hope for the application anyway.
  1455. */
  1456.  
  1457. void SkelApple(Str255 /*char * */ aboutTitle, void (*aboutProc)(void))
  1458. {
  1459.     appleID = 1;
  1460.     appleMenu = NewMenu (appleID, "\p\024");    /* 024 = apple character */
  1461.     if (aboutTitle != nil) 
  1462.     {
  1463.         doAbout = true;
  1464.         AppendMenu (appleMenu, aboutTitle);    /* add About... item title */
  1465.         AppendMenu (appleMenu, "\p(-");        /* add gray line */
  1466.         appleAboutProc = aboutProc;
  1467.     }
  1468.     AddResMenu (appleMenu, 'DRVR');        /* add desk accessories */
  1469.     SkelMenu (appleMenu, DoAppleItem, DoAppleClobber, false, false);
  1470. }
  1471.  
  1472. void SkelHelp(Str255 /*char * */helpTitle, void (*helpProc)(void))
  1473. {
  1474.     if (appleID == 1 && helpTitle != nil) {
  1475.         doHelp = true;
  1476.         InsMenuItem (appleMenu, helpTitle, (doAbout) ? 1 : 0);
  1477.         appleHelpProc = helpProc;
  1478.     }
  1479. }
  1480.  
  1481. void SkelEnableMenu(short mID, Boolean redraw)
  1482. {
  1483.     MenuHandle m = GetMHandle (mID);
  1484.     if (m) {
  1485.         EnableItem (m, 0);
  1486.     }
  1487.     if (redraw)
  1488.         DrawMenuBar ();
  1489. }
  1490.  
  1491. void SkelDisableMenu (short mID, Boolean redraw)
  1492. {
  1493.     MenuHandle m = GetMHandle (mID);
  1494.     if (m) 
  1495.     {
  1496.         DisableItem (m, 0);
  1497.     }
  1498.     if (redraw)
  1499.         DrawMenuBar ();
  1500. }
  1501.  
  1502. void SkelEnableMenus ()
  1503. {
  1504.     register MHandler **mh = mhList;
  1505.     while (mh) {
  1506.         SkelEnableMenu ((**mh).mhID, false);
  1507.         mh = (**mh).mhNext;
  1508.     }
  1509.     DrawMenuBar ();
  1510. }
  1511.  
  1512. void SkelDisableMenus ()
  1513. {
  1514.     register MHandler **mh = mhList;
  1515.     while (mh) {
  1516.         SkelDisableMenu ((**mh).mhID, false);
  1517.         mh = (**mh).mhNext;
  1518.     }
  1519.     DrawMenuBar ();
  1520. }
  1521.  
  1522. /* -------------------------------------------------------------------- */
  1523. /*                    Window-handler interface routines                    */
  1524. /* -------------------------------------------------------------------- */
  1525.  
  1526. /*
  1527.     Install handler for a window.  Remove any previous handler for it.
  1528.     Pass the following parameters:
  1529.  
  1530.     theWind    Pointer to the window to be handled.  Must be created by host.
  1531.     pMouse    Proc to handle mouse clicks in window.  The proc will be
  1532.             passed the point (in local coordinates), the time of the
  1533.             click, and the modifier flags word.
  1534.     pKey    Proc to handle key clicks in window.  The proc will be passed
  1535.             the character and the modifier flags word.
  1536.     pUpdate    Proc for updating window.  TransSkel brackets calls to update
  1537.             procs with calls to BeginUpdate and EndUpdate, so the visRgn
  1538.             is set up correctly.  A flag is passed indicating whether the
  1539.             window was resized or not.  BY CONVENTION, the entire portRect
  1540.             is invalidated when the window is resized.  That way, the
  1541.             handler's update proc can redraw the entire content region
  1542.             without interference from BeginUpdate/EndUpdate.  The flag
  1543.             is set to false after the update proc is called; the
  1544.             assumption is made that it will notice the resizing and
  1545.             respond appropriately.
  1546.     pActivate Proc to execute when window is activated or deactivated.
  1547.             A boolean is passed to it which is true if the window is
  1548.             coming active, false if it's going inactive.
  1549.     pClose    Proc to execute when mouse clicked in close box.  Useful
  1550.             mainly to temp window handlers that want to know when to
  1551.             self-destruct (with SkelRmveWind).
  1552.     pClobber Proc for disposal of handler's data structures
  1553.     pIdle    Proc to execute when no events are pending.
  1554.     frontOnly True if pIdle should execute on no events only when
  1555.             theWind is frontmost, false if executes all the time.  Note
  1556.             that if it always goes, everything else may be slowed down!
  1557.  
  1558.     If a particular procedure is not needed (e.g., key events are
  1559.     not processed by a handler), pass nil in place of the appropriate
  1560.     procedure address.
  1561.  
  1562.     All handler procedures may assume that the port is set correctly
  1563.     at the time they are called.
  1564. */
  1565.  
  1566. Boolean SkelWindow(
  1567.     WindowPtr theWind, 
  1568.     void (*pMouse)(Point,long,short),
  1569.     void (*pKey)(char,unsigned char,short),
  1570.     void (*pUpdate)(Boolean,short), 
  1571.     void (*pActivate)(Boolean),
  1572.     void (*pClose)(void), 
  1573.     void (*pClobber)(void), 
  1574.     void (*pIdle)(void), 
  1575.     Boolean frontOnly)
  1576. {
  1577.     register WHandler    **hHand, *hPtr;
  1578.  
  1579.     if ((hHand = GetWDHandler (theWind)) != nil) {
  1580.         /* remove the window, don't clobber it! */
  1581.         whClobOnRmve = false;
  1582.         SkelRmveWind (theWind);
  1583.         whClobOnRmve = true;
  1584.     }
  1585. /*
  1586.     Get new handler, attach to list of handlers.  It is attached to the
  1587.     beginning of the list, which is simpler; the order is presumably
  1588.     irrelevant to the host, anyway.
  1589. */
  1590.     hHand = SkelNullHandler (theWind);
  1591.     if (hHand) {
  1592. /*
  1593.     Fill in handler fields
  1594. */
  1595.         hPtr = *hHand;
  1596.         hPtr->whMouse = pMouse;
  1597.         hPtr->whKey = pKey;
  1598.         hPtr->whUpdate = pUpdate;
  1599.         hPtr->whActivate = pActivate;
  1600.         hPtr->whClose = pClose;
  1601.         hPtr->whClobber = pClobber;
  1602.         hPtr->whIdle = pIdle;
  1603.         hPtr->whFrontOnly = frontOnly;
  1604.         hPtr->whSized = false;
  1605.         hPtr->whSizedMods = 0;
  1606.     }
  1607.     return (hHand != nil);
  1608. }
  1609.  
  1610.  
  1611. /*
  1612.     Remove a window handler.  This calls the handler's disposal routine
  1613.     and then takes the handler out of the handler list and disposes
  1614.     of it.
  1615.  
  1616.     SkelRmveWind is also called by SkelRmveDlog.
  1617. */
  1618.  
  1619. void SkelRmveWind (WindowPtr theWind)
  1620. {
  1621. register WHandler    **h, **h2;
  1622.  
  1623.     if (whList != nil) {
  1624.         /* if list empty, ignore */
  1625.         if ((**whList).whWind == theWind) 
  1626.         {
  1627.             /* is it the first element? */
  1628.             h2 = whList;
  1629.             whList = (**whList).whNext;
  1630.         }
  1631.         else {
  1632.             for (h = whList; h != nil; h = h2) 
  1633.             {
  1634.                 h2 = (**h).whNext;
  1635.                 if (h2 == nil) {
  1636.                     /* theWind not in list! */
  1637.                     return;
  1638.                 }
  1639.                 if ((**h2).whWind == theWind) 
  1640.                 {
  1641.                     /* found it */
  1642.                     (**h).whNext = (**h2).whNext;
  1643.                     break;
  1644.                 }
  1645.             }
  1646.         }
  1647.         if (whClobOnRmve)
  1648.             DoClobber (h2);                /* call disposal routine */
  1649.         if ((**h2).whCursorRgn) 
  1650.         {
  1651.             DisposeRgn ((**h2).whCursorRgn);
  1652.         }
  1653.         DisposHandle ((Handle) h2);        /* get rid of handler record */
  1654.     }
  1655. }
  1656.  
  1657. /*
  1658.     Set a cursor and a region to allow WaitNextEvent to return mouse-moved
  1659.     events.  This routine should probably also allow a routine to be passed
  1660.     in that would be called when the cursor changed—allowing multiple regions
  1661.     (and multiple cursors) per window, or perhaps a list of regions and
  1662.     cursors.  At the moment the most economical and useful way of doing this
  1663.     is unclear.  -RTS
  1664. */
  1665.  
  1666. void SkelSetCursor(WindowPtr theWind, CursHandle theCursor, RgnHandle theCursorRgn)
  1667. {
  1668.     register WHandler        **h;
  1669.     if ((h = GetWDHandler (theWind)) != nil) 
  1670.     {
  1671.         if ((**h).whHaveCursor = (theCursorRgn != nil)) 
  1672.         {
  1673.             if (!(**h).whCursorRgn) 
  1674.             {
  1675.                 (**h).whCursorRgn = NewRgn ();
  1676.             }
  1677.             CopyRgn (theCursorRgn, (**h).whCursorRgn);
  1678.         }
  1679.         else {
  1680.             if ((**h).whCursorRgn) 
  1681.             {
  1682.                 DisposeRgn ((**h).whCursorRgn);
  1683.             }
  1684.             (**h).whCursorRgn = theCursorRgn;
  1685.         }
  1686.         (**h).whCursor = theCursor;
  1687.     }
  1688. }
  1689.  
  1690. /*
  1691.     Return something about the state of cursor management for this
  1692.     window.  Allows the resize code to do something like:
  1693.     
  1694.     if (SkelGetCursor (nowWin, &cursorHand, &cursorRgn)) {
  1695.         cursorRgn = calcUpdatedCursorRegion (nowWin);
  1696.         SkelSetCursor (nowWin, cursorHand, cursorRgn);
  1697.     }
  1698. */
  1699.  
  1700. Boolean SkelGetCursor(WindowPtr theWind, CursHandle *theCursor, 
  1701.                     RgnHandle *theCursorRgn)
  1702. {
  1703.     register WHandler **h;
  1704.     if ((h = GetWDHandler (theWind)) != nil) 
  1705.     {
  1706.         *theCursor = (**h).whCursor;
  1707.         *theCursorRgn = (**h).whCursorRgn;
  1708.         return ((**h).whHaveCursor);
  1709.     }
  1710.     else 
  1711.         {
  1712.             return (false);
  1713.     }
  1714. }
  1715.  
  1716. /*
  1717.     allow the user to associate an arbitrary long integer with
  1718.     a window
  1719. */
  1720.  
  1721. void SkelSetReference(WindowPtr theWind, long refCon)
  1722. {
  1723.     register WHandler **h;
  1724.     if ((h = GetWDHandler (theWind)) != nil) {
  1725.         (**h).userReference = refCon;
  1726.     }
  1727. }
  1728.  
  1729. long SkelGetReference(WindowPtr theWind)
  1730. {
  1731.     register WHandler **h;
  1732.     if ((h = GetWDHandler (theWind)) != nil) {
  1733.         return ((**h).userReference);
  1734.     }
  1735.     else {
  1736.         return (0L);
  1737.     }
  1738. }
  1739.  
  1740. #ifdef    supportDialogs
  1741.  
  1742. /* -------------------------------------------------------------------- */
  1743. /*                    Dialog-handler interface routines                    */
  1744. /* -------------------------------------------------------------------- */
  1745.  
  1746. /*
  1747.     Install a dialog handler.  Remove any previous handler for it.
  1748.     SkelDialog calls SkelWindow as a subsidiary to install a window
  1749.     handler, then sets the event procedure on return.
  1750.  
  1751.     Pass the following parameters:
  1752.  
  1753.     theDialog    Pointer to the dialog to be handled.  Must be created
  1754.             by host.
  1755.     pEvent    Event-handling proc for dialog events.
  1756.     pClose    Proc to execute when mouse clicked in close box.  Useful
  1757.             mainly to dialog handlers that want to know when to
  1758.             self-destruct (with SkelRmveDlog).
  1759.     pClobber Proc for disposal of handler's data structures
  1760.  
  1761.     If a particular procedure is not needed, pass nil in place of
  1762.     the appropriate procedure address.
  1763.  
  1764.     All handler procedures may assume that the port is set correctly
  1765.     at the time they are called.
  1766. */
  1767.  
  1768. static void SkelDefaultDialogUpdate (Boolean resized, short mods)
  1769. {
  1770. #ifdef applec
  1771. #pragma unused (resized, mods)
  1772. #endif
  1773.     DialogPtr dLog;
  1774.     GetPort ((WindowPtr *) &dLog);
  1775.     UpdtDialog(dLog, dLog->visRgn);
  1776. }
  1777.  
  1778. void SkelDialog(DialogPtr theDialog, 
  1779.     Boolean (*pEvent)(short *, EventRecord *), 
  1780.     Boolean (*pCheck)(short), 
  1781.     Boolean (*pKeys)(short *, EventRecord *), 
  1782.     void (*pUpdate)(Boolean,short), 
  1783.     void (*pClose)(void), 
  1784.     void (*pClobber)(void))
  1785. {
  1786.     register WHandler **h;
  1787.     if (pUpdate == nil)
  1788.         pUpdate = SkelDefaultDialogUpdate;
  1789. #ifdef applec
  1790.     SkelWindow (theDialog, nil,
  1791.                 (void (*)(char, unsigned char, short)) pKeys,
  1792.                 pUpdate, nil, pClose, pClobber,
  1793.                 nil, false);
  1794. #else
  1795.     SkelWindow (theDialog, nil,
  1796.                 (void (*)())pKeys,
  1797.                 pUpdate, nil, pClose, pClobber,
  1798.                 nil, false);
  1799. #endif
  1800.     h = GetWDHandler (theDialog);
  1801.     (**h).whEvent = pEvent;
  1802.     (**h).whCheck = pCheck;
  1803. }
  1804.  
  1805. /*
  1806.     Remove a dialog and its handler
  1807. */
  1808.  
  1809. void SkelRmveDlog (DialogPtr theDialog)
  1810. {
  1811.     SkelRmveWind (theDialog);
  1812. }
  1813.  
  1814. /*
  1815.     Act like modal dialog--but do all the other stuff, too
  1816. */
  1817.  
  1818. short SkelModalDialog(
  1819.     DialogPtr dLog, 
  1820.     Boolean (*pEvent)(short *, EventRecord *), 
  1821.     Boolean (*pCheck)(short), 
  1822.     Boolean (*pKeys)(short *, EventRecord *), 
  1823.     void (*pUpdate)(Boolean,short), 
  1824.     long refCon);
  1825. {
  1826.     register WHandler **h;
  1827.     short itemHit;
  1828.  
  1829.     SkelDialog (dLog, pEvent, pCheck, pKeys, pUpdate, nil, nil);
  1830.     h = GetDHandler (dLog);
  1831.     SkelSetReference (dLog, refCon);
  1832.     (**h).whModal = true;
  1833.     /* default to 0 for check routine */
  1834.     (**h).whItemHit = 0;
  1835.     while (pCheck && (*pCheck) ((**h).whItemHit)) {
  1836.         (**h).whItemHit = 0;
  1837.         SkelOnePass (0);
  1838.         /* in case this got changed by the main loop */
  1839.         SetPort ((GrafPtr) dLog);
  1840.     }
  1841.     itemHit = (**h).whItemHit;
  1842.     SkelRmveDlog (dLog);
  1843.     return (itemHit);
  1844. }
  1845. #endif
  1846.  
  1847.  
  1848. /* -------------------------------------------------------------------- */
  1849. /*                    Miscellaneous interface routines                    */
  1850. /* -------------------------------------------------------------------- */
  1851.  
  1852. /*
  1853.     Override the default sizing limits for a window, or, if theWind
  1854.     is nil, reset the default limits used by SkelWindow.
  1855. */
  1856.  
  1857. void SkelGrowBounds(WindowPtr theWind, short hLo, short vLo, short hHi, short vHi)
  1858. {
  1859.     register WHandler    **h;
  1860.     Rect                r;
  1861.  
  1862.     if (theWind == nil) {
  1863.         SetRect (&growRect, hLo, vLo, hHi, vHi);
  1864.     }
  1865.     else if ((h = GetWDHandler (theWind)) != nil) {
  1866.         SetRect (&r, hLo, vLo, hHi, vHi);
  1867.         (**h).whGrow = r;
  1868.         (**h).whCanGrow = ((hLo != hHi) || (vLo != vHi));
  1869.     }
  1870. }
  1871.  
  1872.  
  1873. /*
  1874.     Set the event mask.  Allow keyup events. -DTH
  1875. */
  1876.  
  1877. void SkelEventMask (short mask)
  1878. {
  1879.     eventMask = mask;
  1880.     if (everyEvent == (eventMask | keyUpMask))
  1881.         SetEventMask (eventMask);
  1882. }
  1883.  
  1884.  
  1885. /*
  1886.     Return the event mask.
  1887. */
  1888.  
  1889. void SkelGetEventMask (short *mask)
  1890. {
  1891.     *mask = eventMask;
  1892. }
  1893.  
  1894.  
  1895. /*
  1896.     Install a background task.  If p is nil, the current task is
  1897.     disabled.  fgTime and bgTime are the timeOut values when
  1898.     WaitNextEvent is being used. -RTS
  1899. */
  1900.  
  1901. void SkelBackground(void (*p)(void), long fgTime, long bgTime)
  1902. {
  1903.     pBkgnd = p;
  1904.     pFGTime = fgTime;
  1905.     pBGTime = bgTime;
  1906. }
  1907.  
  1908.  
  1909. /*
  1910.     Return the current background task.  Return nil if none.
  1911.     Also return the current foreground and background pause times
  1912.     for use with WaitNextEvent.
  1913. */
  1914.  
  1915. void SkelGetBackground(void (**p)(void), long *fgTime, long *bgTime)
  1916. {
  1917.     *p = pBkgnd;
  1918.     *fgTime = pFGTime;
  1919.     *bgTime = pBGTime;
  1920. }
  1921.  
  1922.  
  1923. /*
  1924.     Install an event-inspecting hook.  If p is nil, the hook is
  1925.     disabled.
  1926. */
  1927.  
  1928. void SkelEventHook(Boolean (*p)(EventRecord *))
  1929. {
  1930.     pEvent = p;
  1931. }
  1932.  
  1933.  
  1934. /*
  1935.     Return the current event-inspecting hook.  Return nil if none.
  1936. */
  1937.  
  1938. void SkelGetEventHook(Boolean (**p)(EventRecord *))
  1939. {
  1940.     *p = pEvent;
  1941. }
  1942.  
  1943. /*
  1944.     Install a scrap conversion hook.  If p is nil, the hook is disabled.
  1945. */
  1946.  
  1947. void SkelScrapConvert(void (*p)(Boolean))
  1948. {
  1949.     pScrapConvert = p;
  1950. }
  1951.  
  1952. /*
  1953.     Return the current scrap conversion hook.  Return nil if none.
  1954. */
  1955.  
  1956. void SkelGetScrapConvert(void (**p)(Boolean))
  1957. {
  1958.     *p = pScrapConvert;
  1959. }
  1960.  
  1961. /*
  1962.     Install a multifinder suspend/resume hook.  If p is nil, the hook is disabled.
  1963. */
  1964.  
  1965. void SkelSuspendResumeProc(void (*p)(Boolean))
  1966. {
  1967.     pSuspendResume = p;
  1968. }
  1969.  
  1970. /*
  1971.     Return the current multifinder suspend/resume hook.  Return nil if none.
  1972. */
  1973.  
  1974. void SkelGetSuspendResume(void (**p)(Boolean))
  1975. {
  1976.     *p = pSuspendResume;
  1977. }
  1978.  
  1979. /*
  1980.     Install a multifinder childDied event hook.
  1981. */
  1982.  
  1983. void SkelChildDiedProc(void (*p)(EventRecord *))
  1984. {
  1985.     pChildDied = p;
  1986. }
  1987.  
  1988. /*
  1989.     Return the current multifinder childDied event hook.
  1990. */
  1991.  
  1992. void SkelGetChildDiedProc(void (**p)(EventRecord *))
  1993. {
  1994.     *p = pChildDied;
  1995. }
  1996.  
  1997. /*
  1998.     Install a multifinder childDied event hook.
  1999. */
  2000.  
  2001. void SkelHandleApp4Proc(void (*p)(EventRecord *))
  2002. {
  2003.     pHandleApp4 = p;
  2004. }
  2005.  
  2006. /*
  2007.     Return the current multifinder childDied event hook.
  2008. */
  2009.  
  2010. void SkelGetHandleApp4Proc(void (**p)(EventRecord *))
  2011. {
  2012.     *p = pHandleApp4;
  2013. }
  2014.  
  2015. /*
  2016.     Install a handler for network events
  2017.  
  2018.     This is not really useful anymore under the new systems as networkEvts
  2019.     are be guaranteed to arrive.  The suggested way now is to use callbacks.
  2020.     
  2021. */
  2022.  
  2023. void SkelNetworkProc(void (*p)(EventRecord *))
  2024. {
  2025.     pNetworkProc = p;
  2026. }
  2027.  
  2028. void SkelGetNetworkProc(void (**p)(EventRecord *))
  2029. {
  2030.     *p = pNetworkProc;
  2031. }
  2032.  
  2033. /*
  2034.     Install a zoom proc hook.  If p is nil, the hook is disabled.
  2035. */
  2036.  
  2037. void SkelZoomProc(void (*p)(WindowPtr,short,short,Boolean))
  2038. {
  2039.     pZoomProc = p;
  2040. }
  2041.  
  2042. /*
  2043.     Return the zoom proc hook.  Return nil if none.
  2044. */
  2045.  
  2046. void SkelGetZoomProc(void (**p)(WindowPtr,short,short,Boolean))
  2047. {
  2048.     *p = pZoomProc;
  2049. }
  2050.  
  2051. /*
  2052.     Return the environment record that TransSkel is using -RTS
  2053. */
  2054.  
  2055. SysEnvRec *SkelGetEnvirons ()
  2056. {
  2057.     return (&skelEnvRec);
  2058. }
  2059.  
  2060. /*
  2061.     Check for the existence of a trap
  2062. */
  2063. #define _Unimplemented                  0xA89F
  2064.  
  2065.  
  2066. /* Boolean    SkelCheckTrap(short trapNumber, TrapType trapKind)
  2067. {
  2068. Boolean b;
  2069.  
  2070.     if (trapKind == ToolTrap && (skelEnvRec.machineType > envMachUnknown &&
  2071.             skelEnvRec.machineType < envMacII)) {
  2072.         trapNumber &= 0x03FF;
  2073.         if (trapNumber > 0x01FF) { */
  2074.             /* ToolTraps don't exist on these machines */
  2075. /*            trapNumber = _Unimplemented;
  2076.         }
  2077.     }
  2078.     b = NGetTrapAddress (trapNumber, trapKind) != GetTrapAddress (_Unimplemented);
  2079.     return (NGetTrapAddress (trapNumber, trapKind) !=
  2080.                             GetTrapAddress (_Unimplemented));
  2081. }*/
  2082.  
  2083. #ifdef    supportDialogs
  2084.  
  2085. /*
  2086.     Set the mask for event types that will be passed to dialogs.
  2087.     Bit 1 is always set, so that null events will be passed.
  2088. */
  2089.  
  2090. void SkelDlogMask (short mask)
  2091. {
  2092.     dlogEventMask = mask | 1;
  2093. }
  2094.  
  2095.  
  2096. /*
  2097.     Return the current dialog event mask.
  2098. */
  2099.  
  2100. void SkelGetDlogMask (short *mask)
  2101. {
  2102.     *mask = dlogEventMask;
  2103. }
  2104.  
  2105. #endif
  2106.  
  2107. /* attempt to stop crashing from nested SkelOnePasses */
  2108.  
  2109. RgnHandle SkelUseCursorRgn (RgnHandle newRgn)
  2110. {
  2111.     RgnHandle tempRgn;
  2112.     tempRgn = cursorRgn;
  2113.     cursorRgn = newRgn;
  2114.     return (tempRgn);
  2115. }
  2116.